#pragma once

#include <string>
#include <vector>
#include <windows.h>
#include "ITrainer.h"
#include "common.h"
#include "MsgWinApiLastError.h"
#include "ICheat.h"
#include "HotKey.h"
#include "ExtendedVKeyCodes.h"


namespace TLib
{
	enum BUTTON_TYPE
	{
		BT_ABOUT,
		BT_CHEATS
	};

	enum CMSGS
	{
		SET_BUTTON_GEOMETRY = WM_USER
	};

	struct GEOMETRY_PARAMS
	{
		unsigned int x;
		unsigned int y;
		unsigned int w;
		unsigned int h;
	};

	class STrainer : public ITrainer
	{
	protected:	
		// Trainer Window Specific
		HINSTANCE            tr_hInstance;
		std::string          tr_wndTitle;
		HWND                 tr_hWnd;
		std::string          tr_aboutInfo;
		unsigned int         tr_cxWnd;
		unsigned int         tr_cyWnd;
		int                  tr_wndIconId;
		int                  tr_wndBackBmpId;

		// Trainer Data Specific
		std::vector<ICheat*> d_cheats;
		
		// Game hacked specifics
		HWND                 g_hWnd;
		std::string          g_title;

		HANDLE GetGameProcessHandle();
	private:
		HBRUSH hBrush;
		const std::string tr_wndClassName;
		TRAINER_LIB_API static LRESULT CALLBACK tr_wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
		TRAINER_LIB_API static BOOL CALLBACK tr_cheatDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
	public:
		TRAINER_LIB_API STrainer(const std::string& gameTitle,
			const std::string& trainerTitle,
			unsigned int cxWnd,
			unsigned int cyWnd,
			int iconId = -1,
			int wndBackBmpId = -1);
		TRAINER_LIB_API virtual ~STrainer();
		
		TRAINER_LIB_API virtual int Run();

		inline void setOverrideButtonGeometry(BUTTON_TYPE button, GEOMETRY_PARAMS* geom)
		{SendMessage(tr_hWnd, SET_BUTTON_GEOMETRY, (WPARAM)geom, (LPARAM)&button);}
		
		virtual inline unsigned int getTrainerHeight() const
		{return tr_cyWnd;}

		virtual inline unsigned int getTrainerWidth() const
		{return tr_cxWnd;}

		virtual inline void addCheat(ICheat* cheat)
		{
			static int c = 0;
			cheat->getHotKey()->setId(c);
			d_cheats.push_back(cheat);
			c++;
		}
		
		virtual inline void removeCheat(unsigned int index)
		{d_cheats.erase(d_cheats.begin() + index);}

		virtual inline ICheat* getCheat(unsigned int index)
		{return d_cheats[index];}

		virtual inline unsigned int getNumberOfCheats()
		{return d_cheats.size();}

		virtual inline HWND getTrainerHWnd()
		{return tr_hWnd;}

		virtual inline HINSTANCE getTrainerHInstance()
		{return tr_hInstance;}

		virtual inline HWND getGameHWnd()
		{
			if (!IsWindow(g_hWnd))
				g_hWnd = FindWindow(NULL, g_title.c_str());
			return g_hWnd;
		}
		
		virtual inline void setTrainerTitle(const std::string& title)
		{
			tr_wndTitle = title;
			SetWindowText(tr_hWnd, tr_wndTitle.c_str());
		}
		virtual inline const std::string& getTrainerTitle() const
		{return tr_wndTitle;}

		virtual inline void setAboutInfo(const std::string& aboutString)
		{this->tr_aboutInfo = aboutString;}
		
		virtual inline const std::string& getGameTitle() const
		{return g_title;}

		virtual inline const std::string& getAboutInfo() const
		{return tr_aboutInfo;}
	};
}